package com.nuo.backend.modules.security.config;

import cn.hutool.core.util.StrUtil;
import com.nuo.backend.common.utils.JwtUtils;
import com.nuo.backend.modules.security.service.SecUserService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @description: TODO 验证 jwt
 * @author nuo
 * @date 2022/12/18 1:42
 * @version 1.0
 */
public class JwtAuthenticationFilter extends BasicAuthenticationFilter {


	@Autowired
	JwtUtils jwtUtils;

	@Autowired
	UserDetailServiceImpl userDetailService;

	@Autowired
	SecUserService secUserService;

	public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
		super(authenticationManager);
	}

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

		String jwt = request.getHeader(jwtUtils.getHeader());

		if (StrUtil.isBlankOrUndefined(jwt)) {
			// 没有jwt直接放行
			chain.doFilter(request, response);
			return;
		}

		Claims claim = jwtUtils.getClaimByToken(jwt);
		if (claim == null) {
			throw new JwtException("token 异常");
		}
		if (jwtUtils.isTokenExpired(claim)) {
			// 会注入进验证失败的异常中
			throw new JwtException("token 已过期");
		}

		String username = claim.getSubject();

		// TODO 将token信息存放, 权限设置 null 的话, 后续无法鉴权

		// TODO 1.配置 session 的话可以直接从上下文拿
		// UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, null, SecurityContextHolder.getContext().getAuthentication().getAuthorities());
		// TODO 2.未配置 session 的话就查库吧
		UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, null, userDetailService.getUserAuthority(secUserService.getByUsername(username).getUserId()));

		SecurityContextHolder.getContext().setAuthentication(token);

		// 放行
		chain.doFilter(request, response);

	}
}
